<?php
/*********************************************
  CPG Dragonfly™ CMS
  ********************************************
  Copyright © 2004 - 2007 by CPG-Nuke Dev Team
  http://dragonflycms.org

  Dragonfly is released under the terms and conditions
  of the GNU GPL version 2 or any later version

  $Source$
  $Revision$
  $Author$
  $Date$
**********************************************/
/*
	Future dev notes regarding IPv6
	- http://ietf.org/rfc/rfc2374.txt
	- http://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing
	- IPv6 addresses are usually composed of two logical parts:
	  64-bit network prefix, and a 64-bit host-addressing part (MAC)
	| 3|  13 | 8 |   24   |   16   |          64 bits               |
	+--+-----+---+--------+--------+--------------------------------+
	|FP| TLA |RES|  NLA   |  SLA   |         Interface ID           |
	|  | ID  |   |  ID    |  ID    |                                |
	+--+-----+---+--------+--------+--------------------------------+
     | Routing Prefix   | Subnet |
		 +------------------+--------+
	Where
		FP           Format Prefix (001)
		TLA ID       Top-Level Aggregation Identifier
		RES          Reserved for future use
		NLA ID       Next-Level Aggregation Identifier
		SLA ID       Site-Level Aggregation Identifier
		INTERFACE ID Interface Identifier
	- So the most interesting types for banning is:
	  aaaa:aabb:bbbb:cccc:zzzz:zzzz:zzzz:zzzz
		a 3 bytes TLA (routing) http://sixxs.net/tools/grh/dfp/
		b 3 bytes NLA organizations (may have sub-levels)
		c 2 bytes SLA individual organization subnets (may have sub-levels)
		z The last 8 bytes (although it can be spoofed)
*/

if (!defined('ADMIN_PAGES')) { exit; }
if (!can_admin('security')) { die('Access Denied'); }

$pagetitle .= ' '._BC_DELIM.' Security';
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
$page_url = isset($_GET['page']) && intval($_GET['page']) ? '&amp;page='.intval($_GET['page']) : '';

if ($page < 1) { $page = 1; }
$per_page = 30;
$limit = "LIMIT $per_page OFFSET ".(($page-1)*$per_page);

/*
0:200 = ip:shield
0:203 = ip
0:800 = ip:bad
0:802 = unknow user-agent
0:803 = ip:flood
1:200 = bot:verified
1:203 = bot:
1:802 = bot:bad
1:803 = bot:flood
3:801 = referer:bad
4:801 = email, referer:bad (deprecated)
6:200 = mac:verified
6:800 = mac:bad
9:200 = hostname:verified
9:800 = hostname:bad
10:800 = in_dns_bl

dnsbl.tornevall.org/?do=usage
1	  Proxy has been scanned
2	  Proxy is working
4	  Will be changed!-- Tagged as proxy from Blitzed (R.I.P) See SFS for more information
8	  Proxy was tested, but timed out on connection
16	Proxy was tested but failed at connection
32	Proxy was tested but the IP was different to the one connected at (Including TOR)
64  IP marked as "abusive host". Primary target is web-form spamming (Includes dnsbl_remote)
128	Proxy has a different anonymous-state (web-based proxies, like anonymouse, etc)
*/

function get_cache_type($type, $status, $log='')
{
	$code = $type.':'.$status;
	$ret = array('?' => '', 'bg' => '', 'op' => '');
	switch ($code):
		case '0:200':
		case '0:800': $ret['?'] = htmlprepare($log); break;
		case '0:802': $ret['?'] = 'unknow user-agent'; break;
		case '0:803': $ret['?'] = 'ip:flood'; break;
		case '1:802': $ret['?'] = 'bot:bad'; break;
		case '1:803': $ret['?'] = 'bot:flood'; break;
		case '3:801': $ret['?'] = 'referer:bad'; break;
		case '4:801': $ret['?'] = 'referer:bad (deprecated)'; break;
		case '6:800': $ret['?'] = 'mac:bad'; break;
		case '6:803': $ret['?'] = 'mac:flood'; break;
		case '9:200': $ret['?'] = 'host:shield'; break;
		case '9:800': $ret['?'] = 'host:bad'; break;
		case '9:803': $ret['?'] = 'host:flood'; break;
		case '10:800':$ret['?'] = htmlprepare($log); break;
	endswitch;

	if (200 == $status) $ret['bg'] = 'bg-ok';
	else if (800 <= $status) $ret['bg'] = 'bg-error';
	if (between($status, 802, 803)) $ret['op'] = 'logs';

	return $ret;
}

Dragonfly_Admin_Cp::section_name('Dragonfly CMS Firewall');
Dragonfly_Admin_Cp::section_menu('submenu_inline', array(
	'logs' => 'Logs',
	'ips' => 'IPs',
	'bots' => _BOTS,
	'hostnames' => 'Hostnames',
	'referers' => 'Referers',
	'emails' => 'e-Mails',
	'stopfspam' => 'Stop Forum Spam'
	)
);

# No Spam
if (isset($_GET['stopfspam']))
{
	require('header.php');
	GraphicAdmin('_AMENU0');
	OpenTable();
	$cpgtpl->display('submenu_inline');
	$cpgtpl->assign_vars(array(
		'L_BAN_NAME' => '',
		'L_BAN_TYPE' => '',
		'S_PAGE' => 'stopfspam',
		'S_EMPTY_LIST' => true
	));
	$cpgtpl->set_handle('options', 'admin/security/list.html');
	$cpgtpl->display('options');
	return;
}
# Bots
else if (isset($_GET['bots']))
{
	if (Security::check_post())
	{
		# Delete from tables
		if (isset($_POST['change']))
		{
			$db->update('security_agents',
				array('agent_ban'  => intval($_POST['change_to'])),
				array('agent_name' => $_POST['change'])
			);
			$db->delete('security_cache', "name='{$_POST['change']}'");
			$db->optimize('security_cache');
			URL::redirect(URL::admin('&amp;bots'.$page_url));
		}
		else if (!empty($_POST['delete']))
		{
			$db->delete('security_agents',
				array('agent_name' => $_POST['delete'])
			);
			$db->optimize('security_agents');
			URL::redirect(URL::admin('&amp;bots'.$page_url));
		}
		else if (!empty($_POST['save']))
		{
			# Insert new entry
			$_POST['ua_name'] = trim($_POST['ua_name']);
			$_POST['ua_fullname'] = trim($_POST['ua_fullname']);

			if (empty($_POST['ua_name']))     cpg_error(sprintf(_ERROR_NOT_SET, 'User agent name'));
			if (empty($_POST['ua_fullname']))	cpg_error(sprintf(_ERROR_NOT_SET, 'Detection string'));

			if (preg_match('#^(bot|other|crawler)s?$#i', $_POST['ua_name'])) cpg_error('The user agent name is reserved');
			if ('bot' == empty($_POST['ua_fullname'])) cpg_error(sprintf(_ERROR_NOT_SET, 'The user agent detection string is reserved'));

			if (!preg_match('#^[a-z0-9_\- ]+$#i', $_POST['ua_name']))
				cpg_error(sprintf(_ERROR_BAD_FORMAT, 'User Agent name'));
			if (!preg_match('#^[a-z0-9_\- \/\(\)]+$#i', $_POST['ua_fullname']))
				cpg_error(sprintf(_ERROR_BAD_FORMAT, 'User Agent string'));
			if (!empty($_POST['ua_hostname']) && !Dragonfly_Net::validHostname($_POST['ua_hostname']))
				cpg_error(sprintf(_ERROR_BAD_FORMAT, 'User Agent hostname'));

			$ua_url = empty($_POST['ua_url']) ? null : trim($_POST['ua_url']);

			if (preg_match('#^http://#', $ua_url))
				$ua_url = substr($ua_url, 7);
			if (false === strpos($ua_url, '.'))
				cpg_error(sprintf(_ERROR_BAD_FORMAT, _URL));

				$db->insert('security_agents', array(
				'agent_name'     => $_POST['ua_name'],
				'agent_fullname' => $_POST['ua_fullname'],
				'agent_hostname' => !empty($_POST['ua_hostname']) ? $_POST['ua_hostname'] : null,
				'agent_url'      => $ua_url,
				'agent_ban'      => intval($_POST['ua_ban_type']),
				'agent_desc'     => !empty($_POST['ban_details']) ? $_POST['ban_details'] : null
			));
		}
		URL::redirect(URL::admin('&amp;bots'.$page_url));
	}
	else if (!empty($_GET['bots']))
	{
		$pagetitle .= ' '._BC_DELIM.' Bot Details';
		require('header.php');
		GraphicAdmin('_AMENU0');
		OpenTable();
		$cpgtpl->display('submenu_inline');
		$bot = $db->escape_string($_GET['bots']);
		if ($row = $db->uFetchAssoc('SELECT * FROM '.$prefix."_security_agents WHERE agent_name='$bot'")) {
			$cpgtpl->assign_vars(array(
				'S_BOT_NAME' => $row['agent_name'],
				'S_BOT_UA' => $row['agent_fullname'],
				'S_BOT_DNS' => $row['agent_hostname'],
				'U_BOT_HOME' => $row['agent_url'] ? 'http://'.$row['agent_url'] : '',
				'S_BOT_DESC' => $row['agent_desc']
			));
			$cpgtpl->set_handle('au_details', 'admin/security/bot_details.html');
			$cpgtpl->display('au_details');
		}
		return;
	}
	# Bots admin
	$pagetitle .= ' '._BC_DELIM.' Bots';
	require('header.php');
	GraphicAdmin('_AMENU0');
	OpenTable();
	$cpgtpl->display('submenu_inline');
	$count = $db->count('security_agents');
	pagination('&amp;bots&amp;page=', ceil($count/$per_page), 1, $page, true, false);
	Dragonfly_Admin_Cp::list_header(
		'list',
		'User Agent',
		'Status',
		'Options',
		''
	);
	if ($count && $result = $db->query('SELECT agent_name, agent_ban, agent_hostname FROM '.$prefix."_security_agents ORDER BY agent_name $limit")) {
		while ($row = $result->fetch_assoc()) {
			$bg = !$row['agent_hostname'] ?: 'bg-ok';
			Dragonfly_Admin_Cp::list_value(array(
				array(
					'url' => URL::admin('&amp;bots='.$row['agent_name']),
					'text' => $row['agent_name']
				),
				array(
					'text' => $row['agent_ban'] ? 'Banned' : 'Allowed'
				),
				array(
					'quick' => 'change',
					'action' => URL::admin('&amp;bots'.$page_url),
					'value' => $row['agent_name'],
					'change_to' => (0 > $row['agent_ban'] ? 0 : -1),
					'text' => (0 > $row['agent_ban'] ? 'Allow' : 'Ban')
				),
				array(
					'quick' => 'delete',
					'action' => URL::admin('&amp;bots'.$page_url),
					'value' => $row['agent_name'],
					'text' => _DELETE
				)
			), $bg);
		}
	}
	$cpgtpl->display('list');
	CloseTable();
	return;
}
# Domains
else if (isset($_GET['domains']) && Security::check_post())
{
	$MAIN_CFG->set('_security', 'email',    intval($_POST['emails']));
	$MAIN_CFG->set('_security', 'referers', intval($_POST['referers']));
	$MAIN_CFG->set('_security', 'hostnames', intval($_POST['hostnames']));
	if (!empty($_POST['domain_name']) && (between($_POST['domain_type'], 2, 3) || between($_POST['domain_type'], 8, 9))) {
		$domain_name = $db->escape_string($_POST['domain_name']);
		$domain_type = intval($_POST['domain_type']);
		if (false === strpos($domain_name,'.')) { cpg_error(sprintf(_ERROR_BAD_FORMAT, 'Domain name')); }
		$db->query('INSERT INTO '.$prefix."_security_domains (ban_string, ban_type) VALUES ('$domain_name', $domain_type)");
	}
	URL::redirect(URL::admin('security'));
}
# Hostnames
else if (isset($_GET['hostnames']))
{
	if (Security::check_post())
	{
		if (!empty($_POST['delete']))
		{
			$delete = $db->escape_string($_POST['delete']);
			$db->query('DELETE FROM '.$prefix."_security_domains WHERE ban_string='$delete' AND ban_type IN (8,9)");
			$db->optimize_table($prefix.'_security');
		}
		else if (!empty($_POST['shield']) && preg_match('#^[a-z0-9\.\-]+$#i', $_POST['shield']))
		{
			$db->update('security_domains', array('ban_type'=>8), "ban_string='{$_POST['shield']}'");
		}
		else if (!empty($_POST['ban']) && preg_match('#^[a-z0-9\.\-]+$#i', $_POST['ban']))
		{
			$db->update('security_domains', array('ban_type'=>9), "ban_string='{$_POST['ban']}'");
		}
		URL::redirect(URL::admin('&amp;hostnames'.$page_url));
	}
	$pagetitle .= ' '._BC_DELIM.' Hostnames';
	require('header.php');
	GraphicAdmin('_AMENU0');
	OpenTable();
	$cpgtpl->display('submenu_inline');
	$count = $db->count('security_domains', 'ban_type IN (8,9)');
	pagination('&amp;hostnames&amp;page=', ceil($count/$per_page), 1, $page, true, false);
	Dragonfly_Admin_Cp::list_header(
		'list',
		_NAME,
		'Status',
		'Options',
		''
	);
	if ($count && $result = $db->query('SELECT ban_string, ban_type FROM '.$prefix."_security_domains WHERE ban_type IN (8,9) ORDER BY ban_string $limit")) {
		while ($row = $db->fetch_array($result, SQL_ASSOC)) {
			$bg = 8 == $row['ban_type'] ? 'bg-ok' : '';
			Dragonfly_Admin_Cp::list_value(array(
				array(
					'text' => $row['ban_string']
				),
				array(
					'text' => 9 == $row['ban_type'] ? 'Banned' : 'Shielded'
				),
				array(
					'quick' => 9 == $row['ban_type'] ? 'shield' : 'ban',
					'action' => URL::admin('&amp;hostnames'.$page_url),
					'value' => $row['ban_string'],
					'text' => 9 == $row['ban_type'] ? 'Shield' : 'Ban'
				),
				array(
					'quick' => 'delete',
					'text' => _DELETE,
					'action' => URL::admin('&amp;hostnames'.$page_url),
					'value' => urlencode($row['ban_string'])
				)
			), $bg);
		}
	}
	$cpgtpl->display('list');
	return;
}
# E-mails
else if (isset($_GET['emails']))
{
	if (Security::check_post())
	{
		if (!empty($_POST['delete']))
		{
			$delete = $db->escape_string($_POST['delete']);
			$db->query('DELETE FROM '.$prefix."_security_domains WHERE ban_string='$delete' AND ban_type=2");
			$db->optimize_table($prefix.'_security');
		}
		URL::redirect(URL::admin('&amp;emails'.$page_url));
	}
	$pagetitle .= ' '._BC_DELIM.' Email domains';
	require('header.php');
	GraphicAdmin('_AMENU0');
	OpenTable();
	$cpgtpl->display('submenu_inline');
	$count = $db->count('security_domains', 'ban_type=2');
	pagination('&amp;emails&amp;page=', ceil($count/$per_page), 1, $page, true, false);
	Dragonfly_Admin_Cp::list_header(
		'list',
		_NAME,
		'Status',
		'Options'
	);
	if ($count && $result = $db->query('SELECT ban_string FROM '.$prefix."_security_domains WHERE ban_type=2 ORDER BY ban_string $limit")) {
		while ($row = $db->fetch_array($result, SQL_ASSOC)) {
			Dragonfly_Admin_Cp::list_value(array(
				array(
					'text' => $row['ban_string']
				),
				array(
					'text' => 'Banned'
				),
				array(
					'quick' => 'delete',
					'text' => _DELETE,
					'action' => URL::admin('&amp;emails'.$page_url),
					'value' => urlencode($row['ban_string'])
				)
			));
		}
	}
	$cpgtpl->display('list');
	return;
}
# Floods
else if (isset($_GET['flooding']))
{
	if (Security::check_post()) {
		if (isset($_POST['delay']))   $MAIN_CFG->set('_security', 'delay', intval($_POST['delay']));
		if (isset($_POST['debug']))   $MAIN_CFG->set('_security', 'debug', intval($_POST['debug']));
		URL::redirect(URL::admin());
	}
}
# Logs
elseif (isset($_GET['logs']))
{
	if (Security::check_post())
	{
		if (!empty($_POST['shield']) && $ip = Dragonfly_Net::filterIP(trim($_POST['shield'])))
		{
			$ip = $db->escapeBinary($ip['ipn']);
			if ($db->exec("INSERT INTO {$prefix}_security_ips (ipn_s, type) VALUES ($ip, 8)")) {
				$db->query("DELETE FROM {$prefix}_security_cache WHERE ipn=$ip");
			}
			URL::redirect(URL::admin('&amp;logs'.$page_url));
		}
		else if (!empty($_POST['ban']) && $ip = Dragonfly_Net::filterIP(trim($_POST['ban'])))
		{
			$ip = $db->escapeBinary($ip['ipn']);
			if ($db->exec("INSERT INTO {$prefix}_security_ips (ipn_s, type) VALUES ($ip, 0)")) {
				$db->query("DELETE FROM {$prefix}_security_cache WHERE ipn=$ip");
			}
			URL::redirect(URL::admin('&amp;logs'.$page_url));
		}
		else if (!empty($_POST['delete']) && $ip = Dragonfly_Net::filterIP(trim($_POST['delete'])))
		{
			$ip = $db->escapeBinary($ip['ipn']);
			$db->query('DELETE FROM '.$prefix."_security_cache WHERE ipn=$ip");
			$db->optimize_table($prefix.'_security');
			URL::redirect(URL::admin('&amp;logs'.$page_url));
		}
		else {
			cpg_error(sprintf(_ERROR_BAD_FORMAT, 'IP address'));
		}
	}
	else if (!empty($_GET['logs']))
	{
		$_GET['logs'] = trim($_GET['logs']);
		if (!$ip = Dragonfly_Net::filterIP($_GET['logs']))
			cpg_error(sprintf(_ERROR_BAD_FORMAT, 'IP address'));

		$ip = $db->escapeBinary($ip['ipn']);
		$pagetitle .= ' '._BC_DELIM.' Log details';
		require('header.php');
		GraphicAdmin('_AMENU0');
		OpenTable();
		$cpgtpl->display('submenu_inline');

		if ($row = $db->uFetchAssoc('SELECT * FROM '.$prefix."_security_cache WHERE ipn=$ip")) {
			$cache = get_cache_type($row['type'], $row['status']);
			$log = false;
			if (empty($row['log'])) {
				$row['log'] = 'empty';
			} else {
				if ($log = unserialize(trim($row['log']))) {
					for ($i=0; $i<5; ++$i) {
						$log[$i]['S_TIME']    = formatDateTime($log[$i]['S_TIME'], _DATESTRING);
						$log[$i]['S_UA']      = empty($log[$i]['S_UA']) ? 'empty' : htmlprepare($log[$i]['S_UA']);
						$log[$i]['S_URI']     = htmlprepare($log[$i]['S_URI']);
						$log[$i]['S_REFERER'] = htmlprepare($log[$i]['S_REFERER']);
						$cpgtpl->assign_block_vars('log', $log[$i]);
					}
					$log = true;
				}
			}

			$cpgtpl->assign_vars(array(
				'S_BOT_NAME' => $row['name'] ?: inet_ntop($row['ipn']),
				'S_BOT_UA' => $log ? '' : htmlprepare($row['log']),
				'S_BOT_DNS' => htmlprepare($row['hostname']),
				'U_BOT_HOME' => '',
				'S_BOT_DESC' => $cache['?']
			));
			$cpgtpl->set_handle('au_details', 'admin/security/bot_details.html');
			$cpgtpl->display('au_details');
		}
		return;
	}

	$cpgtpl->set_handle('block-logs', 'admin/security/block-logs.html');
	$block = array(
		'bid' => 'fcplogs',
		'view' => 2,
		'side' => 'r',
		'title' => _TB_TASKS,
		'content' => $cpgtpl->to_string('block-logs')
	);
	Blocks::custom($block);
	$pagetitle .= ' '._BC_DELIM.' Cache';
	require('header.php');
	GraphicAdmin('_AMENU0');
	OpenTable();
	$cpgtpl->display('submenu_inline');
	$count = $db->count('security_cache');
	if ($page <= ceil($count/$per_page)) {
		pagination('&amp;logs&amp;page=', ceil($count/$per_page), 1, $page, true, false);
	}
	Dragonfly_Admin_Cp::list_header(
		'list',
		'Details',
		'Expires in',
		'Options',
		'',
		''
	);
	$date = new DateTime('now', new DateTimeZone('UTC'));
	if ($count && $result = $db->query('SELECT * FROM '.$prefix."_security_cache ORDER BY ttl $limit")) {
		while ($row = $db->fetch_array($result, SQL_ASSOC)) {
			$ip = inet_ntop($row['ipn']);
			$cache = get_cache_type($row['type'], $row['status'], $row['log']);
			$cache['?'] = $cache['op'] ? '<a href="'.URL::admin("&amp;{$cache['op']}=".$ip)."\">{$cache['?']}</a>" : $cache['?'];

			$name = $ip .'<br /><strong>';
			$name .= $cache['?'].' '.$row['name'];
			$name .= '</strong> ' .htmlprepare($row['hostname']);
			$ttl = new DateTime();
			$ttl->setTimestamp((int) $row['ttl']);
			$ttl = $date->diff($ttl);
			if ($ttl->d) $ttl->h += $ttl->d * 24;

			Dragonfly_Admin_Cp::list_value(array(
				array(
					'text' => $name
				),
				array(
					'text' => $ttl->invert ? 'Expired' : ( !$ttl->h ? $ttl->format('%im') : $ttl->format('%hh %im'))
				),
				array(
					'quick' => 'shield',
					'action' => URL::admin('&amp;logs'.$page_url),
					'value' => $ip,
					'text' => 'Shield',
					'disabled' => 200 == $row['status']
				),
				array(
					'quick' => 'ban',
					'action' => URL::admin('&amp;logs'.$page_url),
					'value' => $ip,
					'text' => 'Ban',
					'disabled' => between($row['status'], 800, 802)
				),
				array(
					'quick' => 'delete',
					'action' => URL::admin('&amp;logs'.$page_url),
					'value' => $ip,
					'text' => _DELETE
				)
			), $cache['bg']);
		}
	}
	$cpgtpl->display('list');
	return;
}
# IPs
else if (isset($_GET['ips']))
{
	if (Security::check_post())
	{
		if (!empty($_POST['delete']) && $ip = Dragonfly_Net::filterIP(trim($_POST['delete'])))
		{
			$ipn = $db->escapeBinary($ip['ipn']);
			$db->query('DELETE FROM '.$prefix."_security_ips WHERE ipn_s=$ipn");
			$db->optimize_table($prefix.'_security_ips');
			URL::redirect(URL::admin('&amp;ips'.$page_url));
		}
		else if (!empty($_POST['shield']) && $ip = Dragonfly_Net::filterIP(trim($_POST['shield'])))
		{
			$ipn = $db->escapeBinary($ip['ipn']);
			$db->update('security_ips', array('type'=>8), 'ipn_s='.$ipn);
			URL::redirect(URL::admin('&amp;ips'.$page_url));
		}
		else if (!empty($_POST['ban']) && $ip = Dragonfly_Net::filterIP(trim($_POST['ban'])))
		{
			$ipn = $db->escapeBinary($ip['ipn']);
			$db->update('security_ips', array('type'=>0), 'ipn_s='.$ipn);
			URL::redirect(URL::admin('&amp;ips'.$page_url));
		}
		else if (!empty($_POST['ip_s']))
		{
			# y.y.y.y/cidr?
			if (!$ip = Dragonfly_Net::filterIPwCIDR(trim($_POST['ip_s']))) {
				$ipn_s = Dragonfly_Net::filterIP(trim($_POST['ip_s']));
				if (!empty($_POST['ip_e'])) {
					$ipn_e = Dragonfly_Net::filterIP(trim($_POST['ip_e']));
				}
			}
			if (!empty($ip['cidr'])) {
				$ipn_s = $ip['ipn_s'];
				$ipn_e = $ip['ipn_e'];
			} else {
				$ipn_s = $ipn_s['ipn'];
				$ipn_e = !empty($ipn_e) ? $ipn_e['ipn'] : null;
			}
			if ($ipn_e) {
				if ($ipn_s > $ipn_e) {
					$ip = $ipn_e;
					$ipn_s = $ipn_e;
					$ipn_e = $ip;
				}
			}
			$ipn_s = $db->escapeBinary($ipn_s);
			$ipn_e =  $ipn_e ? $db->escapeBinary($ipn_e) : 'DEFAULT';
			$details = !empty($_POST['details']) ? "'".$db->escape_string($_POST['details'])."'" : 'DEFAULT';
			$type = isset($_POST['type']) ? intval($_POST['type']) : 0;
			$type = $type == 8 ? 8 : 0;
			$db->query('INSERT INTO '.$prefix."_security_ips (ipn_s, ipn_e, type, details) VALUES ($ipn_s, $ipn_e, $type, $details)");
			URL::redirect(URL::admin('&amp;ips'));
		}
		cpg_error('Nothing specified');
	}
	$pagetitle .= ' '._BC_DELIM.' IP\'s';
	require('header.php');
	GraphicAdmin('_AMENU0');
	OpenTable();
	$cpgtpl->display('submenu_inline');
	$count = $db->count('security_ips');
	pagination('&amp;ips&amp;page=', ceil($count/$per_page), 1, $page, true, false);
	Dragonfly_Admin_Cp::list_header(
		'list',
		'IP / IP Range',
		'Status',
		'Options',
		''
	);
	if ($count && $result = $db->query('SELECT * FROM '.$prefix."_security_ips ORDER BY ipn_s")) {
		while ($row = $db->fetch_array($result, SQL_ASSOC)) {
			$ip = inet_ntop($row['ipn_s']);
			$url = $text = $ip;
			if ($row['ipn_e'] && $ipe = inet_ntop($row['ipn_e'])) {
				$text .= ' - '.$ipe;
			}
			$bg = !$row['type'] ?: 'bg-ok';
			Dragonfly_Admin_Cp::list_value(array(
				array(
					//'url' => URL::admin('&amp;ips='.$url),
					'text' => $text . '<br />'.htmlprepare($row['details'])
				),
				array(
					'text' => !$row['type'] ? 'Banned' : 'Shielded'
				),
				array(
					'quick' => !$row['type'] ? 'shield' : 'ban',
					'action' => URL::admin('&amp;ips'.$page_url),
					'value' => $url,
					'text' => !$row['type'] ? 'Shield' : 'Ban'
				),
				array(
					'quick' => 'delete',
					'action' => URL::admin('&amp;ips'.$page_url),
					'value' => $url,
					'text' => _DELETE
				)
			), $bg);
		}
	}
	$cpgtpl->display('list');
	return;
}
# Referers
else if (isset($_GET['referers']))
{
	if (Security::check_post())
	{
		if (!empty($_POST['delete']))
		{
			$mark = $db->escape_string($_POST['delete']);
			$db->sql_query('DELETE FROM '.$prefix."_security_domains WHERE ban_string='$mark' AND ban_type=3");
			$db->optimize('security_domains');
		}
		URL::redirect(URL::admin('&amp;referers'.$page_url));
	}
	$pagetitle .= ' '._BC_DELIM.' Referers';
	require('header.php');
	GraphicAdmin('_AMENU0');
	OpenTable();
	$cpgtpl->display('submenu_inline');
	$count = $db->count('security_domains', 'ban_type=3');
	pagination('&amp;referers&amp;page=', ceil($count/$per_page), 1, $page, true, false);
	Dragonfly_Admin_Cp::list_header(
		'list',
		_NAME,
		'Status',
		'Options'
	);
	if ($count && $result = $db->query('SELECT ban_string FROM {security_domains} WHERE ban_type=3 ORDER BY ban_string '.$limit, Poodle_SQL::ADD_PREFIX)) {
		while ($row = $db->fetch_array($result, SQL_ASSOC)) {
			Dragonfly_Admin_Cp::list_value(array(
				array('text' => $row['ban_string']),
				array('text' => 'Banned'),
				array('quick' => 'delete', 'action' => URL::admin('&amp;referers'.$page_url), 'value' => $row['ban_string'], 'text' => _DELETE)
			));
		}
	}
	$cpgtpl->display('list');
	return;
}
# DNS black lists
else if (isset($_GET['dns_bl']) && Security::check_post())
{
	$srv = array('dns_bl_srv_1', 'dns_bl_srv_2', 'dns_bl_srv_3');
	$exc = array('dns_bl_exc_1', 'dns_bl_exc_2', 'dns_bl_exc_3');
	foreach ($srv as $val) {
		$_POST[$val] = trim($_POST[$val]);
		if (empty($_POST[$val]) || Dragonfly_Net::validHostname($_POST[$val]))
			$MAIN_CFG->set('_security', $val, $_POST[$val]);
	}
	foreach ($exc as $val) {
		$_POST[$val] = trim($_POST[$val]);
		if (empty($_POST[$val]) || preg_match('#^[a-f0-9\.\:]+$#i', $_POST[$val]))
			$MAIN_CFG->set('_security', $val, $_POST[$val]);
	}
	URL::redirect(URL::admin());
}
else if (Security::check_post())
{

	if (isset($_POST['bots']))     $MAIN_CFG->set('_security', 'bots',     intval($_POST['bots']));
	if (isset($_POST['ips']))      $MAIN_CFG->set('_security', 'ips',      intval($_POST['ips']));
	if (isset($_POST['uas']))      $MAIN_CFG->set('_security', 'uas',      intval($_POST['uas']));
	if (isset($_POST['flooding'])) $MAIN_CFG->set('_security', 'flooding', intval($_POST['flooding']));
	if (isset($_POST['bantime']))  $MAIN_CFG->set('_security', 'bantime',  intval($_POST['bantime']));
	if (isset($_POST['dns_bl']))   $MAIN_CFG->set('_security', 'dns_bl_active', intval($_POST['dns_bl']));
	if (isset($_POST['ttl'])) {
		$ttl = intval($_POST['ttl']);
		if ($ttl) $MAIN_CFG->set('_security', 'cachettl', $ttl*86400);
	}
	if (isset($_POST['dns'])) {
		if (empty($_POST['dns']) || Dragonfly_Net::validHostname($_POST['dns'], true) || Dragonfly_Net::filterIP($_POST['dns']))
			$MAIN_CFG->set('server', 'dns', trim($_POST['dns']));
	}
		//if (isset($_POST['stopforumspam'])) { $db->sql_query('UPDATE '.$prefix."_config_custom SET cfg_value='".intval($_POST['stopforumspam'])."' WHERE cfg_name='_security' AND cfg_field='debug'"); }
	URL::redirect(URL::admin());
}

$type = 0;
$ip_s = $ip_e = null;
if (!empty($_GET['ip_s'])) {
	if (!$ip = Dragonfly_Net::filterIPwCIDR(trim($_GET['ip_s']))) {
		$ip_s = Dragonfly_Net::filterIP(trim($_GET['ip_s']));
		if (!empty($_GET['ip_e'])) {
			$ip_e = Dragonfly_Net::filterIP(trim($_GET['ip_e']));
		}
	}
	if (!empty($ip['cidr'])) {
		$ip_s = $ip['ip_s'];
		$ip_e = $ip['ip_e'];
	} else {
		$ip_s = $ip_s['ip'];
		$ip_e = !empty($ip_e) ? $ip_e['ip'] : null;
	}
	$type = isset($_GET['type']) ? intval($_GET['type']) : 0;
	$type = $type == 8 ? 8 : 0;
}
$sections = array(
	'general' => array(
		'title' => 'General',
		'toggle'    => 'fcp', // true or prefix
		'items' => array(
			'ttl'     => array(
				'title' => 'Cache time to live (in days)',
				'value' => $MAIN_CFG->_security->cachettl/86400,
				'type' => 'text', 'size' => 2, 'maxsize' => 2),
			'bantime' => array(
				'title' => _BAN_TIP,
				'value' => $MAIN_CFG->_security->bantime,
				'type' => 'select', 'options' => array(60=>'1 Minute',300=>'5 Minutes',900=>'15 Minutes',3600=>'1 Hour',43200=>'12 Hours')),
			'uas'     => array(
				'title' => 'Block unknown user agent',
				'value' => $MAIN_CFG->_security->uas,
				'type' => 'select', 'options' => array(0=>_NO, 1=>_YES)),
			'dns'     => array(
				'title' => 'DNS server',
				'value' => $MAIN_CFG->server->dns,
				'type' => 'text',
				'help' => '<em>Enter an hostname, an IPv4 or an IPv6.<br />It must be a recursive DNS server</em>'
			),
		)
	),
	'flooding' => array(
		'title'     => 'Floodings',
		'iscfg'     => $MAIN_CFG->_security->flooding,
		'toggle'    => 'fcp', // true or prefix
		'items'     => array(
			'delay'    => array(
				'title' => _FLOODING_TIP,
				'value' => $MAIN_CFG->_security->delay,
				'type' => 'select', 'options' => array(4=>'Normal', 2=>'High', 1=>'Emergency')),
			'debug'    => array(
				'title' => _DEBUG,
				'value' => $MAIN_CFG->_security->debug,
				'type' => 'select', 'options' => array(0=>_NO, 1=>_YES))
		)
	),
	'bots' => array(
		'title' => _BOTS,
		'iscfg' => $MAIN_CFG->_security->bots,
		'toggle'=> 'fcp', // true or prefix
		'items' => array(
			'item-text-only0' => '<strong>Add a new bot by user agent</strong>',
			'ua_name'      => array(
				'required' => 1,
				'title' => 'Unique name',
				'type' => 'text', 'maxlength' => 35, 'size' => 23),
			'ua_fullname'  => array(
				'required' => 1,
				'title' => 'Detection string', 'type' => 'text', 'size' => 23),
			'ua_hostname'  => array(
				'title' => 'Hostname',
				'type' => 'text', 'size' => 23,
				'help' => '<em>will protect the client</em>'),
			'ua_url'       => array(
				'title' => 'Informational '._URL,
				'type' => 'text', 'size' => 23),
			'ua_ban_type'  => array(
				'title' => 'Type',
				'type' => 'select', 'options' => array(0=>'Allowed', -1=>'Blocked')),
			'ban_details'  => array(
				'title' => 'Description',
				'type' => 'textarea', 'rows' => 2, 'cols' => 23)
				/*'item-extra-data0' => '<em>optional: include a CIDR in "IPv4 start" or use "IPv4 end" instead</em>',
				'ban_ipv4_s[]' => array('required' => 1, 'title' => 'IPv4 start', 'type' => 'text', 'size' => 18, 'maxsize' => 18),
				'ban_ipv4_e[]' => array('title' => 'IPv4 end', 'type' => 'text', 'size' => 15, 'maxsize' => 15),
				'new_range'    => array('title' => 'Create additional IP range(s)', 'type' => 'button', 'value' => 'Add another IP range', 'extra' => 'onclick="newRange.add();"'),
				'item-text-only0' => '<div id="ranges"></div>'*/
		)
	),
	'domains' => array(
		'title'  => 'Domains',
		'toggle'    => 'fcp', // true or prefix
		'items' => array(
			'emails' => array(
				'title' => 'e-Mails',
				'value' => $MAIN_CFG->_security->email,
				'type' => 'select', 'options' => array(0=>_INACTIVE, 1=>_ACTIVE),
				'help' => '<em>example.com, example.</em>'
			),
			'referers' => array(
				'title' => 'Referers',
				'value' => $MAIN_CFG->_security->referers,
				'type' => 'select', 'options' => array(0=>_INACTIVE, 1=>_ACTIVE),
				'help' => '<em>.example.com, example., .example, example</em>'
			),
			'hostnames' => array(
				'title' => 'Hostnames',
				'value' => $MAIN_CFG->_security->hostnames,
				'type' => 'select', 'options' => array(0=>_INACTIVE, 1=>_ACTIVE),
				'help' => '<em>example.com</em>'
			),
			'item-text-only0' => '<strong>Add a new domain</strong>',
			'domain_type' => array(
				'title' => 'Domain type',
				'type' => 'select', 'options' => array(2=>'Blocked e-mail', 3=>'Blocked referer', 8=>'Protected hostname', 9=>'Blocked hostname')
			),
			'domain_name' => array (
				'title' => 'Detection string',
				'type' => 'text', 'size' => 23
			)
		)
	),
	'ips' => array(
		'title'  => 'IPs',
		'iscfg'  => $MAIN_CFG->_security->ips,
		'toggle' => 'fcp', // true or prefix
		'items'  => array(
			'item-extra-data0' => '<em>To add a range of IPs: use IP start and IP end, or IP start/CIDR</em>',
			'type' => array(
				'title' => 'Type',
				'value' => ($ip_s ? $type : 0),
				'type' => 'select', 'options' => array(0=>'Blocked', 8=>'Protected')),
			'ip_s' => array(
				'title' => 'IPv4/IPv6 start',
				'value' => ($ip_s ? $ip_s : ''),
				'type' => 'text', 'maxlength' => 43, 'size' => 23),
			'ip_e' => array(
				'title' => 'IPv4/IPv6 end',
				'value' => ($ip_e ? $ip_e : ''),
				'type' => 'text', 'maxlength' => 39, 'size' => 23),
			'details'=> array(
				'title' => _DESCRIPTION,
				'type' => 'textarea', 'rows' => 2, 'cols' => 23)
		)
	),
	'dns_bl' => array(
		'title'  => 'DNS block lists',
		'iscfg'  => $MAIN_CFG->_security->dns_bl_active,
		'toggle' => 'fcp', // true or prefix
		'items' => array(
			'dns_bl_srv_1' =>	array(
				'title' => '1. Hostname',
				'value' => $MAIN_CFG->_security->dns_bl_srv_1,
				'type' => 'text', 'maxlength' => '216', 'size' => 23),
			'dns_bl_exc_1' => array(
				'title' => '1. Exclude list <em>(if any)</em>',
				'value' => $MAIN_CFG->_security->dns_bl_exc_1,
				'type' => 'text', 'maxlength' => '39', 'size' => 23),
			'dns bl_srv_2' => array(
				'title' => '2. Hostname',
				'value' => $MAIN_CFG->_security->dns_bl_srv_2,
				'type' => 'text', 'maxlength' => '216', 'size' => 23),
			'dns_bl_exc_2' => array(
				'title' => '2. Exclude list <em>(if any)</em>',
				'value' => $MAIN_CFG->_security->dns_bl_exc_2,
				'type' => 'text', 'maxlength' => '39', 'size' => 23),
			'dns_bl_srv_3' => array(
				'title' => '3. Hostname',
				'value' => $MAIN_CFG->_security->dns_bl_srv_3,
				'type' => 'text', 'maxlength' => '216', 'size' => 23),
			'dns_bl_exc_3' => array(
				'title' => '3. Exclude list <em>(if any)</em>',
				'value' => $MAIN_CFG->_security->dns_bl_exc_3,
				'type' => 'text', 'maxlength' => '39', 'size' => 23),
		)
	),
/*'honeypot' => array(
		'title'  => 'Honey Pot',
		'iscfg'  => $MAIN_CFG['_security']['honeypot'],
		'toggle'    => 'fcp', // true or prefix
		'items' => array(
			'honeypot_host'    => array('title' => 'Host',                   'value' => $MAIN_CFG['_security']['honeypot_host'],    'type' => 'text', 'maxlength' => 255),
			'honeypot_key'     => array('title' => 'Key',                    'value' => $MAIN_CFG['_security']['honeypot_key'],     'type' => 'text', 'maxlength' => 12,'size' => 12),
			'honeypot_0_log'   => array('title' => 'Search engine: log',     'value' => $MAIN_CFG['_security']['honeypot_0_log'],   'type' => 'select', 'options' => array(0=>_NO, 1=>_YES)),
			'honeypot_1'       => array('title' => 'Suspicious',             'value' => $MAIN_CFG['_security']['honeypot_1'],       'type' => 'select', 'options' => array(0=>_INACTIVE, 1=>_ACTIVE)),
			'honeypot_1_days'  => array('title' => 'Suspicious: days',       'value' => $MAIN_CFG['_security']['honeypot_1_days'],  'type' => 'text', 'maxlength' => 3, 'size' => 3),
			'honeypot_1_threat'=> array('title' => 'Suspicious, threat',     'value' => $MAIN_CFG['_security']['honeypot_1_threat'],'type' => 'text', 'maxlength' => 3, 'size' => 3),
			'honeypot_1_log'   => array('title' => 'Suspicious: log',        'value' => $MAIN_CFG['_security']['honeypot_1_log'],   'type' => 'select', 'options' => array(0=>_NO, 1=>_YES)),
			'honeypot_2'       => array('title' => 'Harvester',              'value' => $MAIN_CFG['_security']['honeypot_2'],       'type' => 'select', 'options' => array(0=>_INACTIVE, 1=>_ACTIVE)),
			'honeypot_2_days'  => array('title' => 'Harvester: days',        'value' => $MAIN_CFG['_security']['honeypot_2_days'],  'type' => 'text', 'maxlength' => 3, 'size' => 3),
			'honeypot_2_threat'=> array('title' => 'Harvester: threat',      'value' => $MAIN_CFG['_security']['honeypot_2_threat'],'type' => 'text', 'maxlength' => 3, 'size' => 3),
			'honeypot_2_log'   => array('title' => 'Harvester: log',         'value' => $MAIN_CFG['_security']['honeypot_2_log'],   'type' => 'select', 'options' => array(0=>_NO, 1=>_YES)),
			'honeypot_4'       => array('title' => 'Comment Spammer',        'value' => $MAIN_CFG['_security']['honeypot_4'],       'type' => 'select', 'options' => array(0=>_INACTIVE, 1=>_ACTIVE)),
			'honeypot_4_days'  => array('title' => 'Comment Spammer: days',  'value' => $MAIN_CFG['_security']['honeypot_4_days'],  'type' => 'text', 'maxlength' => 3, 'size' => 3),
			'honeypot_4_threat'=> array('title' => 'Comment Spammer: threat','value' => $MAIN_CFG['_security']['honeypot_4_threat'],'type' => 'text', 'maxlength' => 3, 'size' => 3),
			'honeypot_4_log'   => array('title' => 'Comment Spammer: log',   'value' => $MAIN_CFG['_security']['honeypot_4_log'],   'type' => 'select', 'options' => array(0=>_NO, 1=>_YES))
		)
	),
	'sfs' => array(
		'title'  => 'Stop Forums Spam',
		'iscfg'  => $MAIN_CFG['_security']['sfs'],
		'toggle' => 'fcp',
		'items' => array(
			'sfs_key' => array('title' => 'Key',  'value' => $MAIN_CFG['_security']['sfs_key'],  'type' => 'text', 'maxlength' => 12,'size' => 12),
			'dnsbl_1' => array('title' => 'Mode', 'value' => $MAIN_CFG['_security']['sfs_mode'], 'type' => 'select', 'options' => array(0=>'Log only', 1=>'Approve registration', 2 => 'Enforce')),
		)
	)
*/
);

JS::add('themes/default/javascript/addipv4range.js');
Dragonfly_Admin_Cp::section_items('section', $sections);
require_once('header.php');
GraphicAdmin('_AMENU0');
OpenTable();
$cpgtpl->display('submenu_inline');
$cpgtpl->assign_vars(array(
	'L_TYPE' => _TYPE,
	'L_PROTECTION' => _PROTECTION,
	'L_ACTIVE' => _ACTIVE,
	'L_INACTIVE' => _INACTIVE,
	'S_PAGE' => 'security'
));

$cpgtpl->display('section');
CloseTable();
